package com.mindai.esper.monitor.biz.epl;

import com.espertech.esper.client.EPAdministrator;
import com.espertech.esper.client.EPStatement;
import com.mindai.esper.monitor.biz.constant.EsperConstant;
import com.mindai.esper.monitor.biz.domain.model.EsperDbModel;
import com.mindai.esper.monitor.biz.domain.model.EsperEplModel;
import com.mindai.esper.monitor.biz.domain.model.EsperMethodModel;
import com.mindai.esper.monitor.biz.domain.model.EsperSchemaModel;
import com.mindai.esper.monitor.biz.domain.reponsitory.impl.EsperRepositoryImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Created by Administrator on 2017/8/15.
 */
@Service
@Slf4j
public class CommonEsperEplService {

    @Autowired
    private EsperRepositoryImpl esperRepository;

    /**
     * 添加自定义的事件
     */
    public void addSchemas(EPAdministrator admin) {

        //TODO 待后续需要时放开
        List<EsperSchemaModel> esperSchemaModels = esperRepository.queryEsperSchema(null);

        String schemaEpl = "create schema EsperRequest (bizOrderId String, bizSysCode String,requestSysCode String) ";
        admin.createEPL(schemaEpl);
        //        Collection<List<EsperSchemaModel>> schemas = allSchema.values();
        //        for (List<EsperSchemaModel> esperSchemaModelList : schemas) {
        //            for (EsperSchemaModel esperSchemaModel : esperSchemaModelList) {
        //                if (schemaStateMap.containsKey(esperSchemaModel.getId())) {
        //                    schemaStateMap.get(esperSchemaModel.getId()).add(this.admin.createEPL(esperSchemaModel.getCreateSchemaSql()));
        //                } else {
        //                    List<EPStatement> epsList = new ArrayList<EPStatement>();
        //                    epsList.add(this.admin.createEPL(esperSchemaModel.getCreateSchemaSql()));
        //                    schemaStateMap.put(esperSchemaModel.getId(), epsList);
        //                }
        //                if (groupKeyMap.containsKey(esperSchemaModel.getId())) {
        //                    groupKeyMap.get(esperSchemaModel.getId()).add(esperSchemaModel.getFieldGroupKey());
        //                } else {
        //                    Set<String> groupKeySet = new HashSet<String>();
        //                    groupKeySet.add(esperSchemaModel.getFieldGroupKey());
        //                    groupKeyMap.put(esperSchemaModel.getId(), groupKeySet);
        //                }
        //                log.info("Add Data EsperSchemaModel : " + esperSchemaModel.getCreateSchemaSql());
        //            }
        //        }
    }

    /**
     * 添加Esper对应的数据源信息
     */
    public void addEsperDb() {
        //TODO 待后续需要时放开
        List<EsperDbModel> esperDbModels = esperRepository.queryEsperDbModel(null);
        //        for (EsperDbModel esperDbModel : esperDbModels) {
        //            Properties pps = new Properties();
        //            String[] props = esperDbModel.getProps();
        //            ConfigurationDBRef configDB = new ConfigurationDBRef();
        //            for (String prop : props) {
        //                String[] fields = prop.split("=");
        //                if (fields.length != 2) continue;
        //                if ("initialSize".equals(fields[0])) {
        //                    pps.put(fields[0], Integer.parseInt(fields[1]));
        //                } else {
        //                    pps.put(fields[0], fields[1]);
        //                }
        //            }
        //
        //            configDB.setDataSourceFactory(pps, esperDbModel.getSourceFactory());
        //            //set cache reference type
        //            ConfigurationCacheReferenceType cacheReferenceType = null;
        //            if ("WEAK".equals(esperDbModel.getCacheReferenceType())) {
        //                cacheReferenceType = ConfigurationCacheReferenceType.WEAK;
        //            } else if ("SOFT".equals(esperDbModel.getCacheReferenceType())) {
        //                cacheReferenceType = ConfigurationCacheReferenceType.SOFT;
        //            } else {
        //                cacheReferenceType = ConfigurationCacheReferenceType.HARD;
        //            }
        //            configDB.setExpiryTimeCache(esperDbModel.getMaxAgeSeconds(), esperDbModel.getPurgeIntervalSeconds(), cacheReferenceType);
        //
        //            //set connection lifecycle
        //            ConfigurationDBRef.ConnectionLifecycleEnum connectionLifecycle = null;
        //            if ("RETAIN".equals(esperDbModel.getConnectionLifecycle())) {
        //                connectionLifecycle = ConfigurationDBRef.ConnectionLifecycleEnum.RETAIN;
        //            } else if ("POOLED".equals(esperDbModel.getConnectionLifecycle())) {
        //                connectionLifecycle = ConfigurationDBRef.ConnectionLifecycleEnum.POOLED;
        //            }
        //            configDB.setConnectionLifecycleEnum(connectionLifecycle);
        //            this.configuration.addDatabaseReference(esperDbModel.getDbName(), configDB);
        //            log.info("Add Data Source : " + esperDbModel.getDbName());
        //
        //        }
    }

    /**
     * 添加对应的公共方法
     *
     * @return
     */
    public void addMethods() {
        //TODO 待提交
        List<EsperMethodModel> esperMethodModels = esperRepository.queryEsperMethodModel(null);
        //        for (EsperMethodModel esperMethodModel : esperMethodModels) {
        //            ConfigurationMethodRef methodRef = new ConfigurationMethodRef();
        //            ConfigurationCacheReferenceType cacheReferenceType = null;
        //            if ("WEAK".equals(esperMethodModel.getCacheReferenceType())) {
        //                cacheReferenceType = ConfigurationCacheReferenceType.WEAK;
        //            } else if ("SOFT".equals(esperMethodModel.getCacheReferenceType())) {
        //                cacheReferenceType = ConfigurationCacheReferenceType.SOFT;
        //            } else {
        //                cacheReferenceType = ConfigurationCacheReferenceType.HARD;
        //            }
        //            methodRef.setExpiryTimeCache(esperMethodModel.getMaxAgeSeconds(), esperMethodModel.getPurgeIntervalSeconds(), cacheReferenceType);
        //            Class clazz = null;
        //            try {
        //                clazz = Class.forName(esperMethodModel.getMethodName());
        //            } catch (ClassNotFoundException e) {
        //                e.printStackTrace();
        //            }
        //            if (clazz == null) continue;
        //            log.info("Add customer esperMethodModel : " + esperMethodModel.getMethodName());
        //            configuration.addMethodRef(clazz, methodRef);
        //            configuration.addImport(esperMethodModel.getMethodName());
        //        }
    }


    /**
     * 创建Epl表达式
     */
    public void addEsperEpl(EPAdministrator admin) {

        List<EsperEplModel> esperEplModels = esperRepository.queryEsperEpl(null);
        EPStatement state = null;
        String eplSql = "select bizOrderId, bizSysCode,requestSysCode from EsperRequest";
        EsperEplModel esperEplModel = new EsperEplModel();
        esperEplModel.setEplId("TEST00000000000000000000001");
        state = admin.createEPL(eplSql);
        state.addListener(new EsperEplListener(esperEplModel));

//        for (EsperEplModel esperEplModel : esperEplModels) {
//            eplSql = esperEplModel.getEplSql();
//            String[] eplSqls = eplSql.trim().split(EsperConstant.SEMICOLON_SYMBOL);
//            for (int i = 0; i < eplSqls.length; i++) {
//
//                if (!StringUtils.isBlank(eplSqls[i])) {
//                    if (i == eplSqls.length - 1) {
//                        log.info("Add statistic esperEplModel : " + eplSql + ", name: " + esperEplModel.getEplName());
//                        state = admin.createEPL(eplSqls[i].trim());
//                        state.addListener(new EsperEplListener(esperEplModel));
//                    } else {
//                        admin.createEPL(eplSqls[i].trim());
//                    }
//                }
//
//            }
//        }
    }


//    public void recreateEpl(int eplId, EsperEplModel esperEplModel) {
//        EPStatement epStatement = eplStateMap.get(eplId);
//        if (epStatement != null && !epStatement.isDestroyed()) {
//            epStatement.removeAllListeners();
//            epStatement.destroy();
//
//        }
//        String eplSql = esperEplModel.getEplSql();
//        String[] eplSqls = eplSql.trim().split(";");
//
//        for (int i = 0; i < eplSqls.length; i++) {
//
//            if (!StringUtils.isBlank(eplSqls[i])) {
//                if (i == eplSqls.length - 1) {
//                    epStatement = this.admin.createEPL(eplSqls[i].trim());
//                    log.info("Add statistic esperEplModel : " + eplSql);
//                    if (epStatement != null) eplStateMap.put(esperEplModel.getEplId(), epStatement);
//                } else {
//                    admin.createEPL(eplSqls[i].trim());
//                }
//            }
//
//        }
//        epStatement.addListener(new EsperEplListener(esperEplModel));
//        log.info("Recreate statistic esperEplModel : " + eplSql);
//    }


//    public void recreateSchema(int schemaId, EsperSchemaModel esperSchemaModel) {
//        List<EPStatement> schemaStates = schemaStateMap.get(schemaId);
//        for (EPStatement schemaState : schemaStates) {
//            if (schemaState != null && !schemaState.isDestroyed()) schemaState.destroy();
//            groupKeyMap.get(esperSchemaModel.getId()).clear();
//        }
//        addSchemas(esperSchemaModel.getId());
//    }

//    public void recreateMethod(EsperMethodModel esperMethodModel) {
//        EsperMethodModel md = this.allMethods.get(esperMethodModel.getMethodName());
//        if (md != null) this.configuration.removeImport(md.getMethodName());
//        ConfigurationMethodRef methodRef = new ConfigurationMethodRef();
//        ConfigurationCacheReferenceType cacheReferenceType = null;
//        if ("WEAK".equals(esperMethodModel.getCacheReferenceType())) {
//            cacheReferenceType = ConfigurationCacheReferenceType.WEAK;
//        } else if ("SOFT".equals(esperMethodModel.getCacheReferenceType())) {
//            cacheReferenceType = ConfigurationCacheReferenceType.SOFT;
//        } else {
//            cacheReferenceType = ConfigurationCacheReferenceType.HARD;
//        }
//        methodRef.setExpiryTimeCache(esperMethodModel.getMaxAgeSeconds(), esperMethodModel.getPurgeIntervalSeconds(), cacheReferenceType);
//        Class clazz = null;
//        try {
//            clazz = Class.forName(esperMethodModel.getMethodName());
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        this.configuration.addMethodRef(clazz, methodRef);
//        this.configuration.addImport(esperMethodModel.getMethodName());
//        LOG.info("Recreate EsperMethodModel : " + esperMethodModel.getMethodName());
//    }

//    public void recreateDB(EsperDbModel esperDbModel) {
//        EsperDbModel db = this.allDbs.get(esperDbModel.getDbName());
//        if (db != null) return;
//        Properties pps = new Properties();
//        String[] props = esperDbModel.getProps();
//        ConfigurationDBRef configDB = new ConfigurationDBRef();
//        for (String prop : props) {
//            String[] fields = prop.split("=");
//            if ("initialSize".equals(fields[0])) {
//                pps.put(fields[0], Integer.parseInt(fields[1]));
//            } else {
//                pps.put(fields[0], fields[1]);
//            }
//        }
//
//        configDB.setDataSourceFactory(pps, esperDbModel.getSourceFactory());
//        //set cache reference type
//        ConfigurationCacheReferenceType cacheReferenceType = null;
//        if ("WEAK".equals(esperDbModel.getCacheReferenceType())) {
//            cacheReferenceType = ConfigurationCacheReferenceType.WEAK;
//        } else if ("SOFT".equals(esperDbModel.getCacheReferenceType())) {
//            cacheReferenceType = ConfigurationCacheReferenceType.SOFT;
//        } else {
//            cacheReferenceType = ConfigurationCacheReferenceType.HARD;
//        }
//        configDB.setExpiryTimeCache(esperDbModel.getMaxAgeSeconds(), esperDbModel.getPurgeIntervalSeconds(), cacheReferenceType);
//
//        //set connection lifecycle
//        ConfigurationDBRef.ConnectionLifecycleEnum connectionLifecycle = null;
//        if ("RETAIN".equals(esperDbModel.getConnectionLifecycle())) {
//            connectionLifecycle = ConfigurationDBRef.ConnectionLifecycleEnum.RETAIN;
//        } else if ("POOLED".equals(esperDbModel.getConnectionLifecycle())) {
//            connectionLifecycle = ConfigurationDBRef.ConnectionLifecycleEnum.POOLED;
//        }
//        configDB.setConnectionLifecycleEnum(connectionLifecycle);
//        this.configuration.addDatabaseReference(esperDbModel.getDbName(), configDB);
//        LOG.info("Recreate Data Source : " + esperDbModel.getDbName());
//    }
//
//
//    public void refresh(List<Map<Object, Object>> zkDataList) {
//
//        isUpdate = true;
//        try {
//
//            for (Map<Object, Object> zkData : zkDataList) {
//
//                if ("method".equals(zkData.get("type").toString())) {
//                    if (zkData.containsKey("action") && "remove".equals(zkData.get("action"))) {
//                        destory(Integer.parseInt(zkData.get("id").toString()), "method");
//                    } else if (zkData.containsKey("action") && ("update".equals(zkData.get("action")) || "add".equals(zkData.get("action")))) {
//                        EsperMethodModel esperMethodModel = new EsperMethodModel(Integer.parseInt(zkData.get("id").toString()), zkData.get("methodName").toString(), zkData.get("cacheReferenceType").toString(), zkData.get("dbDescribe").toString(), Integer.parseInt(zkData.get("maxAgeSeconds").toString()), Integer.parseInt(zkData.get("purgeIntervalSeconds").toString()));
//                        recreateMethod(esperMethodModel);
//                    }
//                } else if ("epl".equals(zkData.get("type").toString())) {
//                    if (zkData.containsKey("action") && "remove".equals(zkData.get("action"))) {
//                        destory(Integer.parseInt(zkData.get("id").toString()), "epl");
//                    } else if (zkData.containsKey("action") && ("update".equals(zkData.get("action")) || "add".equals(zkData.get("action")))) {
//                        Map<Integer, EsperEplModel> epls = DBConnectionUtils.qetAllEpls(Integer.parseInt(zkData.get("id").toString()));
//                        if (epls.containsKey(Integer.parseInt(zkData.get("id").toString())) && epls.get(Integer.parseInt(zkData.get("id").toString())) != null) {
//                            EsperEplModel esperEplModel = epls.get(Integer.parseInt(zkData.get("id").toString()));
//                            recreateEpl(esperEplModel.getId(), esperEplModel);
//                            esperEplModel = null;
//                        }
//                        epls = null;
//                    }
//                } else if ("db".equals(zkData.get("type").toString())) {
//                    if (zkData.containsKey("action") && "remove".equals(zkData.get("action"))) {
//                        destory(Integer.parseInt(zkData.get("id").toString()), "db");
//                    } else if (zkData.containsKey("action") && ("update".equals(zkData.get("action")) || "add".equals(zkData.get("action")))) {
//                        EsperDbModel esperDbModel = new EsperDbModel(Integer.parseInt(zkData.get("id").toString()), zkData.get("props").toString().split(","), zkData.get("dbName").toString(), zkData.get("connectionLifecycle").toString(), zkData.get("cacheReferenceType").toString(), zkData.get("dbDescribe").toString(), zkData.get("sourceFactory").toString(), Integer.parseInt(zkData.get("maxAgeSeconds").toString()), Integer.parseInt(zkData.get("purgeIntervalSeconds").toString()));
//                        recreateDB(esperDbModel);
//                    }
//                } else if ("schema".equals(zkData.get("type").toString())) {
//                    if (zkData.containsKey("action") && "remove".equals(zkData.get("action"))) {
//                        destory(Integer.parseInt(zkData.get("id").toString()), "schema");
//                    } else if (zkData.containsKey("action") && ("update".equals(zkData.get("action")) || "add".equals(zkData.get("action")))) {
//                        EsperSchemaModel esperSchemaModel = new EsperSchemaModel();
//                        esperSchemaModel.setId(Integer.parseInt(zkData.get("id").toString()));
//                        recreateSchema(esperSchemaModel.getId(), esperSchemaModel);
//                    }
//                }
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            isUpdate = false;
//            this.latch.countDown();
//        }
//
//    }

//    public void destory(Object id, String type) {
//        if ("method".equals(type) && id != null) {
//            EsperMethodModel md = this.allMethods.get(id);
//            if (md != null) this.configuration.removeImport(md.getMethodName());
//            LOG.info("Remove EsperMethodModel : " + md.getMethodName());
//        } else if ("epl".equals(type)) {
//            if (eplStateMap.containsKey(id) && !eplStateMap.get(id).isDestroyed()) {
//                eplStateMap.get(id).destroy();
//                LOG.info("Destroy EsperMethodModel : " + eplStateMap.get(id).getText());
//                eplStateMap.remove(id);
//            }
//        } else if ("db".equals(type)) {
//            if (this.configuration.getDatabaseReferences().containsKey(id)) {
//                this.configuration.getDatabaseReferences().remove(id);
//                LOG.info("Remove Data Source : " + this.configuration.getDatabaseReferences().get(id));
//            }
//        } else if ("schema".equals(type)) {
//            if (schemaStateMap.containsKey(id)) {
//                List<EPStatement> epStatementList = schemaStateMap.get(id);
//                for (EPStatement ePStatement : epStatementList) {
//                    if (!ePStatement.isDestroyed()) {
//                        LOG.info("Destroy Data EsperSchemaModel : " + schemaStateMap.get(id));
//                        ePStatement.destroy();
//                    }
//                }
//            }
//            schemaStateMap.remove(id);
//        }
//    }


}
